package com.example.rwq_test.niuke;

import java.util.HashMap;
import java.util.Map;

/**
 * @Description: lru缓存
 * @Author：dingdang4D
 * @Date：2024/6/6
 */
public class LRUCache {
    int capacity;
    Map<Integer, ListNode> cache;
    ListNode head;
    ListNode tail;
    int size;

    public LRUCache(int capacity) {
        this.capacity = capacity;
        this.cache = new HashMap<>(capacity);
    }

    static class ListNode {
        int key;
        int value;
        ListNode pre;
        ListNode next;

        public ListNode(int key, int value) {
            this.key = key;
            this.value = value;
        }

    }

    public int get(int key) {
        if (cache.containsKey(key)) {
            ListNode cur = cache.get(key);
            if (tail != cur) {
                removeNode(cur);
                setTail(cur);
            }
            return cur.value;
        }
        return -1;
    }

    public void set(int key, int value) {
        ListNode node = new ListNode(key, value);
        if (cache.isEmpty()) {
            setHead(node);
            setTail(node);
            size ++;
        } else if (cache.containsKey(key)) {
            ListNode cur = cache.get(key);
            if (cur == tail && cur.value == value) {
                return;
            }
            removeNode(cur);
            setTail(node);
            if (head == null) {
                setHead(node);
            }
        } else {
            if (size == capacity) {
                cache.remove(head.key);
                removeNode(head);
                size--;
            }
            setTail(node);
            size ++;
        }
        cache.put(key, node);
    }

    private void removeNode(ListNode node) {
        if (node == head && node == tail) {
            head = null;
            tail = null;
            return;
        }
        if (head == node) {
            ListNode next = head.next;
            next.pre = null;
            head.next = null;
            head = next;
        } else if (tail == node) {
            ListNode pre = tail.pre;
            pre.next = null;
            tail.pre = null;
            tail = pre;
        } else {
            node.pre.next = node.next;
            node.next.pre = node.pre;
            node.next = null;
            node.pre = null;
        }

    }

    private void setHead(ListNode node) {
        if (head == null) {
            head = node;
        } else {
            node.pre.next = null;
            node.pre = null;
            head = node;
        }
    }

    private void setTail(ListNode node) {
        if (tail == null) {
            tail = node;
        } else {
            tail.next = node;
            node.pre = tail;
            tail = node;
        }
    }

    public static void main(String... args) {
        LRUCache lruCache = new LRUCache(3);
        lruCache.set(1,1);
        lruCache.set(1,2);
        lruCache.get(1);
    }
}
